Skip to content

Conversation

@pareshjoshij
Copy link

@pareshjoshij pareshjoshij commented Nov 21, 2025

Description

This commit fixes a critical bug in the OTLPLogExporter where _translate_data was returning raw ResourceLogs instead of wrapping them in the expected ExportLogsServiceRequest envelope. This previously caused gRPC export calls to fail with a type error.

Additionally, this fixes a logic flaw in __init__ regarding the timeout argument. It changes the assignment to check if timeout is not None, ensuring that an explicit timeout=0 is respected rather than being overridden by environment variables.

Fixes #4814

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

  • Manual Verification: Created a script to initialize OTLPLogExporter and verify that _translate_data now correctly returns an instance of ExportLogsServiceRequest instead of a raw list.
  • Manual Verification: Verified that initializing OTLPLogExporter(timeout=0) results in the instance having a timeout of 0, whereas previously it defaulted to None or the environment variable.

Does This PR Require a Contrib Repo Change?

  • Yes. - Link to PR:
  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

This commit fixes a critical bug in the OTLP gRPC log exporter where `_translate_data` was returning raw `ResourceLogs` instead of wrapping them in `ExportLogsServiceRequest`. This caused gRPC export calls to fail with a type error.

Additionally, this fixes the `timeout` argument initialization. Previously, passing `timeout=0` would be treated as None due to boolean evaluation; it now checks `if timeout is not None` to correctly respect explicit zero timeouts.
@pareshjoshij pareshjoshij requested a review from a team as a code owner November 21, 2025 04:59
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Nov 21, 2025

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: pareshjoshij / name: Paresh Joshi (7a5d2fe)

self, data: Sequence[ReadableLogRecord]
) -> ExportLogsServiceRequest:
return encode_logs(data)
return ExportLogsServiceRequest(resource_logs=encode_logs(data))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about that:

def encode_logs(
    batch: Sequence[ReadableLogRecord],
) -> ExportLogsServiceRequest:
    return ExportLogsServiceRequest(resource_logs=_encode_resource_logs(batch))

Do tests pass?

credentials=credentials,
headers=headers or environ.get(OTEL_EXPORTER_OTLP_LOGS_HEADERS),
timeout=timeout or environ_timeout,
timeout=timeout if timeout is not None else environ_timeout,
Copy link
Contributor

@xrmx xrmx Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks correct but please add a test and also update it for all the signals. Said that OTLPExporterMixin has the same issue so without updating that too this won't change behavior. Also no idea how the grpc client will behave.

@pareshjoshij
Copy link
Author

Thanks a lot @xrmx sir for the review! Before I continue, can you please confirm if this plan is correct?

Apply the timeout is not None logic across all OTLP exporters (and the mixin if needed) + add tests for None, 0, and positive values.

Revert the encode_logs double-wrap and return the original value as before.
If I make these updates, will the PR be on the right track?

Thanks again for your guidance! 🙏

credentials=credentials,
headers=headers or environ.get(OTEL_EXPORTER_OTLP_LOGS_HEADERS),
timeout=timeout or environ_timeout,
timeout=timeout if timeout is not None else environ_timeout,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both requests and gRPC when a timeout is not set, they will wait forever for the server:

https://grpc.io/docs/guides/deadlines/#deadlines-on-the-client
https://requests.readthedocs.io/en/latest/user/advanced/#timeouts

I don't think we want that ? I think we should always set some upper bound..

An explicit timeout of 0 will cause an error from python requests library. I did not try it for grpc but it might be the same, have you tried it ?

My thinking is we should update the code to explicitly disallow (or ignore?) a timeout of 0, and also to update the code to set some upper bound on the timeout.. WDYT?

If you actually wanted this change you would also have to update this logic in all the exporters (we have similar logic for HTTP):

https://github.com/open-telemetry/opentelemetry-python/blob/main/exporter/opentelemetry-exporter-otlp-proto-grpc/src/opentelemetry/exporter/otlp/proto/grpc/exporter.py#L388C9-L388C21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: OTLP gRPC Log Exporter fails to wrap logs in ExportLogsServiceRequest

3 participants